package dataexchange;


import dataexchange.communication.CommunicationType;
import dataexchange.communication.ICommunication;
import dataexchange.messageconversion.IMessageConversion;
import dataexchange.messageconversion.MessageConversionType;

import javax.naming.CommunicationException;
import java.lang.reflect.ParameterizedType;

/**
 * Created by cwtao on 2017-04-28.
 * 注解@MessageConversionType，子类在不重写{@link #getSendString(Object, Class)}及{@link #getReceiveObject(String, Class)}方法的情况下
 * 必须填加该注解，注明该数据交换类型由Object到字符串的转换类，详情见{@link IMessageConversion}
 *
 * 注解@CommunicationType，子类在不重写{@link #sendData(String)} 方法的情况下
 * 必须填加该注解，注明该数据与外部的通讯类,详见{@link ICommunication}
 */
@MessageConversionType(IMessageConversion.class)
@CommunicationType(ICommunication.class)
public class BaseDataExchangeService<S, R> implements IDataExchangeService<S, R> {

    /**
     * 转为字符串前对实体进行的操作
     * @param srcObject
     * @return
     */
    protected S beforeSendData(S srcObject) {
        return srcObject;
    }

    /**
     *
     * @param srcString
     * @return
     */
    protected String beforeSendString(String srcString) {
        return srcString;
    }

    protected String getSendString(S srcObject,Class<? extends S> srcClazz){
        IMessageConversion messageConversion = getMessageConversionService();
        String sendString;
        if (messageConversion != null) {
            sendString = messageConversion.getSendString(srcObject, getSrcClazz());
        } else {
            throw new RuntimeException("请继承并配置IMessageConversion注解");
        }
        sendString = beforeSendString(sendString);
        return sendString;
    }


    protected String sendData(String sendString) throws CommunicationException {
        Class<? extends ICommunication> communicationServiceClazz = this.getClass().getAnnotation(CommunicationType.class).value();
        ICommunication communicationService1 = DataExchangeBaseServiceFactory.getCommunicationService(communicationServiceClazz);

        return communicationService1.swapData(sendString);
    }

    protected String behandReceiveData(String rString) {
        return rString;
    }

    protected R getReceiveObject(String recString,Class<? extends R> recClazz){
        IMessageConversion messageConversion = getMessageConversionService();
        return messageConversion.getReceiveObject(recString, getReturnClazz());
    }

    protected R behandReceiveString(R recData) {
        return recData;
    }

    @Override
    public final R exchangeData(S sObject) throws CommunicationException {
        sObject = beforeSendData(sObject);
        IMessageConversion messageConversion = getMessageConversionService();
        String sendString = getSendString(sObject, getSrcClazz());
        String recString = sendData(sendString);
        R recObject = getReceiveObject(recString, getReturnClazz());
        recObject = behandReceiveString(recObject);
        return recObject;

    }

    private IMessageConversion getMessageConversionService() {
        Class<? extends IMessageConversion> messageConversionServiceClazz = (Class<? extends IMessageConversion>) this.getClass().getAnnotation(MessageConversionType.class).value();
        if (messageConversionServiceClazz != null) {
            return DataExchangeBaseServiceFactory.getMessageConversionService(messageConversionServiceClazz);
        }
        return null;
    }

    private Class<R> getReturnClazz() {
        return (Class) (((ParameterizedType) this.getClass().getGenericSuperclass())).getActualTypeArguments()[1];
    }

    private Class<S> getSrcClazz() {
        return (Class) (((ParameterizedType) this.getClass().getGenericSuperclass())).getActualTypeArguments()[0];
    }

}
